package scala.cookbook.akka

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Random, Success}
import akka.pattern.FutureTimeoutSupport

/**
  * Created by baiwf on 2017/5/13.
  */
object ch13_Future extends App {
  //non_blocking()
  //onSuccessAndFailure()
  futureMethod()
  //blocking()

  def futureMethod(): Unit = {
    implicit val t = System.currentTimeMillis()

    def longRunningTask(i: Int): Future[Int] = Future {
      println(s"execute long task,i=$i")
      Thread.sleep(500)
      i + 1
    }

    longRunningTask(11).onComplete {
      case Success(value) => println(s"got callback,value=$value")
      case Failure(e) => e.printStackTrace()
    }
    Thread.sleep(1000)
  }

  def onSuccessAndFailure(): Unit = {
    val f = Future {
      Thread.sleep(Random.nextInt(500))
      if (Random.nextInt(500) > 250) throw new Exception("YIkes") else 42
    }

    f onSuccess {
      case result => println(s"Success:$result") //partial function
    }

    f onFailure {
      case t => println(s"except:${t.getMessage}")
    }

    for (i <- 1 to 5) {
      println(i)
      Thread.sleep(100)
    }
    Thread.sleep(1000)
  }

  def non_blocking(): Unit = {
    val f = Future {
      Thread.sleep(Random.nextInt(500))
      42
    }
    println("before onComplete")
    f.onComplete {
      case Success(value) => println(s"got callback,value=$value")
      case Failure(e) => e.printStackTrace()
    }
    for (i <- 1 to 5) {
      println(i)
      Thread.sleep(100)
    }
    Thread.sleep(1000)
  }

  def blocking(): Unit = {
    implicit val baseTime = System.currentTimeMillis()
    val f = Future {
      Thread.sleep(500)
      1 + 1
    }

    f.foreach(println)
    f.map(println)
    //f.flatMap(println)


    val res = Await.result(f, 1 second) //blocking, which bad
    println(res)
    Thread.sleep(1000)
  }
}
